package com.self.match.disruptor;

import com.lmax.disruptor.*;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import net.openhft.affinity.AffinityThreadFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ThreadFactory;

/**
 * @version v1.0
 * @ClassName: DisruptorAutoConfiguration
 * @Description:
 * @Author: Mac
 */
@Configuration
@EnableConfigurationProperties(DisruptorProperities.class)
public class DisruptorAutoConfiguration {

    private DisruptorProperities disruptorProperities;

    public DisruptorAutoConfiguration(DisruptorProperities disruptorProperities) {
        this.disruptorProperities = disruptorProperities;
    }

    @Bean
    public EventFactory<OrderEvent> eventEventFactory(){
        EventFactory<OrderEvent> eventFactory = new EventFactory<OrderEvent>() {
            @Override
            public OrderEvent newInstance() {
                return new OrderEvent();
            }
        };
        return eventFactory;
    }

    @Bean
    public ThreadFactory threadFactory(){
        return new AffinityThreadFactory("Match-Handler:");
    }

    /**
     * @Title: 无锁高效等待策略
     */
    @Bean
    public  WaitStrategy waitStrategy(){
        return new YieldingWaitStrategy();
    }


    @Bean
    public RingBuffer<OrderEvent> ringBuffer(EventFactory<OrderEvent> eventEventFactory,
                                             ThreadFactory threadFactory,
                                             WaitStrategy waitStrategy,
                                             EventHandler<OrderEvent>[] eventHandlers){
        Disruptor<OrderEvent> disruptor = null;
        ProducerType producerType = ProducerType.SINGLE;
        if (disruptorProperities.isMultiProducer()){
            producerType = ProducerType.MULTI;
        }
        disruptor = new Disruptor<OrderEvent>(eventEventFactory,disruptorProperities.getRingBufferSize(),
                threadFactory,producerType,waitStrategy);
        //设置默认的异常处理
        disruptor.setDefaultExceptionHandler(new DisruptorHandlerException());
        //设置消费者，一个消费者代表一个交易对，有对个交易对，就有多少个EventHandler，多个EventHandler并行处理
        disruptor.handleEventsWith(eventHandlers);
        RingBuffer<OrderEvent> ringBuffer = disruptor.getRingBuffer();
        disruptor.start();//开始监听
        //优雅停机
        final Disruptor<OrderEvent> finalDisruptor = disruptor;
        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            finalDisruptor.shutdown();
        },"DisruptorShutdownThread"));
        return ringBuffer;
    }



    @Bean
    public DisruptorTemplate disruptorTemplate(RingBuffer<OrderEvent> ringBuffer){
        return new DisruptorTemplate(ringBuffer);
    }


}
